package com.example.lotterysystem.service.iml;

import cn.hutool.crypto.digest.DigestUtil;
import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.common.utils.JWTUtil;
import com.example.lotterysystem.common.utils.RegexUtil;
import com.example.lotterysystem.controller.param.ShortMessageLoginParam;
import com.example.lotterysystem.controller.param.UserLoginParam;
import com.example.lotterysystem.controller.param.UserPasswordLoginParam;
import com.example.lotterysystem.controller.param.UserRegisterParam;
import com.example.lotterysystem.dao.dataobject.Encrypt;
import com.example.lotterysystem.dao.dataobject.UserDO;
import com.example.lotterysystem.dao.mapper.UserMapper;
import com.example.lotterysystem.service.dto.UserDTO;
import com.example.lotterysystem.service.dto.UserLoginDTO;
import com.example.lotterysystem.service.dto.UserRegisterDTO;
import com.example.lotterysystem.service.enums.UserIdentityEnum;
import com.example.lotterysystem.service.UserService;
import com.example.lotterysystem.service.VerificationCodeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VerificationCodeService verificationCodeService;


    @Override
    public List<UserDTO> findUserInfo(String identity) {
        String identityString =  null == identity ? null : identity;
        // 查表
        List<UserDO> userDOList = userMapper.selectUserListByIdentity(identityString);
        List<UserDTO> userDTOList = userDOList.stream()
                .map(userDO -> {
                    UserDTO userDTO = new UserDTO();
                    userDTO.setUserId(userDO.getId());
                    userDTO.setUserName(userDO.getUserName());
                    userDTO.setEmail(userDO.getEmail());
                    userDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());
                    userDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity().name()));
                    return userDTO;
                }).collect(Collectors.toList());
        return userDTOList;
    }


    @Override
    public UserRegisterDTO register(UserRegisterParam param) {

        checkRegisterInfo(param);


        UserDO userDO=new UserDO();
        userDO.setEmail(param.getMail());
        userDO.setIdentity(UserIdentityEnum.forName(param.getIdentity()));
        userDO.setUserName(param.getName());
        if(StringUtils.hasText(param.getPassword())){
            userDO.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }
        userDO.setPhoneNumber(new Encrypt(param.getPhoneNumber()));


        userMapper.insert(userDO);

        UserRegisterDTO registerDTO=new UserRegisterDTO();
        registerDTO.setUserId(userDO.getId());



            return registerDTO;
    }

    @Override
    public UserLoginDTO userLogin(UserLoginParam param) {
        UserLoginDTO loginDTO;

        // 类型检查与类型转换，java 14及以上版本
        if(param instanceof UserPasswordLoginParam loginParam){
            loginDTO=loginByPasseord(loginParam);
        } else if (param instanceof ShortMessageLoginParam loginParam){
            loginDTO=loginByShortMessage(loginParam);

        }else {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }


        return loginDTO;
    }




    /**
     * 验证码登录
     *
     * @param loginParam
     * @return
     */
    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam loginParam) {
        if (!RegexUtil.checkMobile(loginParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }

        //获取用户信息
        UserDO userDO=userMapper.selectByPhoneNumber(new Encrypt(loginParam.getPhoneNumber()));
        
        if(null==userDO){
            throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);
        } else if (StringUtils.hasText(userDO.getIdentity().name()) &&
        !userDO.getIdentity().name().equalsIgnoreCase(loginParam.getMandatoryIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);

        }

        //校验验证码

        String code = verificationCodeService.getVerificationCode(
                loginParam.getPhoneNumber());
        if (!loginParam.getVerificationCode().equals(code)) {
            throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);
        }



        Map<String,Object> map=new HashMap<>();

        map.put("id",userDO.getId());
        map.put("identity",userDO.getIdentity());


        String token=  JWTUtil.genJwt(map);
        UserLoginDTO loginDTO=new UserLoginDTO();
        loginDTO.setToken(token);
        loginDTO.setIdentity(userDO.getIdentity());
        return loginDTO;
    }

    /**
     * 密码登录
     * @param loginParam
     * @return
     */

    private UserLoginDTO loginByPasseord(UserPasswordLoginParam loginParam) {
        UserDO userDO=null;

        if(RegexUtil.checkMobile(loginParam.getLoginName())){
            userDO=userMapper.selectByPhoneNumber(new Encrypt(loginParam.getLoginName()));
        } else if (RegexUtil.checkMail(loginParam.getLoginName())) {
            userDO=userMapper.selectByMail(loginParam.getLoginName());

        }else {
            throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);
        }

        if (null==userDO){
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        } else if (StringUtils.hasText(userDO.getIdentity().name()) &&
        !userDO.getIdentity().name().equalsIgnoreCase(loginParam.getMandatoryIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }


        //校验密码

        if(!DigestUtil.sha256Hex(loginParam.getPassword())
                .equals(userDO.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }

        Map<String,Object> map=new HashMap<>();

        map.put("id",userDO.getId());
        map.put("identity",userDO.getIdentity());


        String token= JWTUtil.genJwt(map);
        UserLoginDTO loginDTO=new UserLoginDTO();
        loginDTO.setToken(token);
        loginDTO.setIdentity(userDO.getIdentity());
        return loginDTO;

    }










    private void checkRegisterInfo(UserRegisterParam param){

        log.info("  "+param);
        if(null==param){
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }

        if(!RegexUtil.checkMail(param.getMail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }

        if(!RegexUtil.checkMobile(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }

        if(null==UserIdentityEnum.forName(param.getIdentity())){
            throw  new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }


        //管理员密码校验
        if(param.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.name())
                &&!StringUtils.hasText(param.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }

        //密码校验

        if(StringUtils.hasText(param.getPassword())&&!RegexUtil.checkPassword(param.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }

        //检查是否被使用


        if(checkMailUsed(param.getMail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }



        if(checkPhoneUsed(new Encrypt(param.getPhoneNumber()))){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }




    }

    private boolean checkPhoneUsed(Encrypt phone) {
        int count= userMapper.countByPhone(phone);

        return count>0;

    }

    private boolean checkMailUsed(String mail) {
        int count= userMapper.countByMail(mail);
        return count>0;
    }


}
